#include "./PORT/port.h"

/**
 * @brief       DMA基本配置
 *   @note      这里仅对DMA完成一些基础性的配置, 包括: DMA时钟使能 / 设置外设地址 和 存储器地址
 *              其他配置参数(CCR寄存器), 需用户自己另外实现
 *
 * @param       dma_streamx : DMA及数据流, DMA1_Stream0 ~ DMA1_Stream7, DMA2_Stream0 ~ DMA1_Stream7
 * @param       ch          : 通道x, 0~7
 *                            具体某个外设对应哪个DMA, 哪个数据流, 哪个通道, 请参考<<STM32F4xx中文参考手册>> 9.3.3节
 *                            必须设置正确的DMA及通道, 才能正常使用! 
 * @param       par         : 外设地址
 * @param       m0ar        : 存储器0地址
 * @param       m1ar        : 存储器1地址, 使用双缓存的时候才会用到
 * @retval      无
 */
void dma_basic_config(DMA_Stream_TypeDef *dma_streamx,uint32_t ch, uint32_t par, uint32_t m0ar, uint32_t m1ar)
{
    if (dma_streamx > DMA1_Stream7) /* 大于 DMA1_Stream7, 则为DMA2的通道了 */
    {
        RCC->AHB1ENR |= 1 << 22; /* 开启DMA2时钟 */
    }
    else
    {
        RCC->AHB1ENR |= 1 << 21; /* 开启DMA1时钟 */
    }

    delay_ms(5); /* 等待DMA时钟稳定 */

    dma_streamx->CR = (ch & 7) << 25; /* 数据流通道选择, 0 ~ 7 */
    dma_streamx->PAR = par;           /* DMA 外设地址 */
    dma_streamx->M0AR = m0ar;         /* DMA 存储器0地址 */
    dma_streamx->M1AR = m1ar;         /* DMA 存储器1地址 */
    dma_streamx->NDTR = 0;            /* DMA 传输长度清零, 后续在dma_enable函数设置 */
}

/**
 * @brief       开启一次DMA传输
 * @param       dma_streamx : DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
 * @param       ndtr        : 数据传输量
 * @retval      无
 */
void dma_enable(DMA_Stream_TypeDef *dma_streamx, uint16_t ndtr)
{
    dma_streamx->CR &= ~(1 << 0);   /* 关闭DMA传输 */

    while (dma_streamx->CR & 0X1);  /* 确保DMA可以被设置 */

    dma_streamx->NDTR = ndtr;       /* 要传输的数据项数目 */
    dma_streamx->CR |= 1 << 0;      /* 开启DMA传输 */
}

void (*dma2_ch3_callback)(void); // DMA2通道3传输完成回调函数, 用户根据需要自行定义

void DMA2_Channel3_IRQHandler(void)
{

}

